class SyncParallelHook {
  constructor () {
    this.tasks = []
  }

  tap (name, task) {
    this.tasks.push(task)
  }

  tapAsync (name, task) {
    this.tasks.push(task)
  }

  callAsync (...args) {
    const finalCallback = args.pop()
    let index = 0
    const next = () => {
      if (index === this.tasks.length) {
        finalCallback()
        return
      }

      this.tasks[index++](...args, next)
    }

    next(...args, next)
  }

  tapPromise (name, task) {
    this.tasks.push(task)
  }

  promise (...args) {
    const [ first, ...other ] = this.tasks

    return other.reduce(
      (prev, next) => prev.then(() => next(...args)), first(...args)
    )
  }
}

// let hook = new SyncParallelHook(['name'])

/*hook.tapAsync('react', (name, cb) => {
  console.log('react series')
  setTimeout(() => {
    console.log('react', name)
    cb()
  }, 1000)
})

hook.tapAsync('node', (name, cb) => {
  console.log('node series')
  setTimeout(() => {
    console.log('node', name)
    cb()
  }, 1000)
})

hook.callAsync('xyf', () => {
  console.log('end')
})*/


let hook2 = new SyncParallelHook(['name promise'])

hook2.tapPromise('react', (name) => {
  return new Promise(((resolve, reject) => {
    setTimeout(() => {
      console.log('promise: react', name)
      resolve()
    }, 1000)
  }))
})

hook2.tapPromise('node', (name, cb) => {
  return new Promise(((resolve, reject) => {
    setTimeout(() => {
      console.log('promise: node', name)
      resolve()
    }, 1000)
  }))
})

hook2.promise('xyf').then(() => {
  console.log('promise: end')
})

